package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.math.BigDecimal;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodConstantProperties props;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	private VodService vodService;


	/**
	 * 腾讯云点播上传声音
	 * @param file 音频文件
	 * @return
	 */
	@Override
	public JSONObject uploadTrack(MultipartFile file) {
		try {
			String mediaFilePath = UploadFileUtil.uploadTempPath(props.getTempPath(), file);
			VodUploadClient client = new VodUploadClient(props.getSecretId(), props.getSecretKey());
			VodUploadRequest request = new VodUploadRequest();
			request.setMediaFilePath(mediaFilePath);
			VodUploadResponse response = client.upload("ap-guangzhou", request);
			if(response != null) {
				// 表示有响应，拿到对应的响应参数返回
				String mediaFileId = response.getFileId();
				String mediaUrl = response.getMediaUrl();
				JSONObject json = new JSONObject();
				// TODO 此处为了省钱，可以给前端返回一个死的mediaFileId和mediaUrl, 需要的时候打开注释就行
				json.put("mediaFileId", mediaFileId);
				json.put("mediaUrl", mediaUrl);
				return json;
			}
			return null;
		} catch (Exception e) {
			log.error("[云点播上传文件失败：]{}", e);
			throw new RuntimeException("云点播上传失败");
		}
	}

	/**
	 * 保存声音
	 * 1. 保存声音的相关信息-track_info
	 * 2. 更新专辑的包含声音的信息(album_info)
	 * 3. 保存声音的状态信息-track_stat
	 * @param trackInfoVo 保存声音相关信息
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(Long userId, TrackInfoVo trackInfoVo) {
		// 1. 保存声音的相关信息-track_info
		// 1.1 把属性复制
		TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
		// 1.2 设置用户id
		trackInfo.setUserId(userId);
		// 1.3 查出当前专辑的声音数量设置我们的声音顺序
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
		// 1.4 设置当前声音的来源
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
		// 1.5 设置当前声音状态 TODO 这里可以有平台审核 这里先设置为通过了
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		// 1.6 设置音频文件相关信息（文件大小，时长，文件类型）-调用腾讯云点播平台接口获取
		TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
		if (trackMediaInfoVo != null) {
			trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
		}
		// 1.7 保存声音
		trackInfoMapper.insert(trackInfo);
		// 2. 更新专辑的包含声音的信息(album_info)
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
		albumInfoMapper.updateById(albumInfo);
		// 3. 保存声音的状态信息-track_stat
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
	}

	/**
	 * 保存声音状态信息
	 * @param id 声音id
	 * @param statType 声音状态类型
	 */
	@Override
	public void saveTrackStat(Long id, String statType) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(id);
		trackStat.setStatType(statType);
		trackStat.setStatNum(0);
		trackStatMapper.insert(trackStat);
	}

	/**
	 * 获取当前用户声音分页列表
	 * @param pageInfo MP分页对象
	 * @param trackInfoQuery 模糊查询属性
	 * @return
	 */
	@Override
	public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.findUserTrackPage(pageInfo, trackInfoQuery);
	}

	/**
	 * 根据声音id修改声音信息
	 * 1. 修改声音表信息
	 * 2. 拿着修改后的mediaFileId是否重新上传了文件，修改数据库表的数据
	 * @param id 声音id
	 * @param trackInfoVo 修改的声音信息vo
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		String mediaFileId = trackInfo.getMediaFileId(); // 拿到原始的文件唯一标识
		BeanUtil.copyProperties(trackInfoVo, trackInfo);
		// 判断音频文件是否改了
		if (!mediaFileId.equals(trackInfoVo.getMediaFileId())) {
			// 改了，需要去调用云点播的方法获取新的文件的信息入库 （文件大小，类型，持续时间）
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(mediaFileId);
			trackInfo.setMediaType(trackMediaInfo.getType());
			trackInfo.setMediaSize(trackMediaInfo.getSize());
			trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
		}
		// 修改声音信息
		trackInfoMapper.updateById(trackInfo);
	}

	/**
	 * 根据声音id删除声音
	 * 1. 拿到需要删除的声音信息
	 * 2. 对这个声音对应的order_num的后面信息重新编号
	 * 3. 删除声音信息
	 * 4. 修改专辑信息中的声音数量
	 * 5. 删除声音状态信息表的记录
	 * 6. 删除云点播平台的音频信息
	 * @param id 声音id
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long id) {
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		// 调用mapper层的方法进行修改编号
		// update track_info set order_num = order_num - 1 where album_id = ? and order_num > ?
		trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
		// 删除声音信息
		trackInfoMapper.deleteById(id);
		// 修改专辑声音数量
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		albumInfoMapper.updateById(albumInfo);
		// 删除声音状态信息
		LambdaQueryWrapper<TrackStat> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TrackStat::getTrackId, id);
		trackStatMapper.delete(wrapper);
		// 删除云点播平台的音频信息
		vodService.removeTrackMediaInfo(trackInfo.getMediaFileId());
	}
}
